package edu.bbu.cshu.wmpc.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
 * <ul>
 * <li><b><i>SourceCodeWmpc</i></b></li>
 * <li style="list-style: none;"></li>
 * <li style="list-style: none;">
 * Object that contains the content of the input files, and also the formalized content of the input files. A map is provided for the correspondence between the original and formalized lines. Information about the file type is also stored here.
 * 
 * @author WMPC team
 * </li>
 * </ul>
 */ 
public class SourceCodeWmpc {
	/**
	 * <ul>
	 * <li><b><i>type</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * {@link FileTypes}'s type will be the source code.
	 * </li>
	 * </ul>
	 */
	private FileTypes type;
	/**
	 * <ul>
	 * <li><b><i>original</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * An {@link ArrayList}<{@link String}> which contains the original source code.
	 * </li>
	 * </ul>
	 */
	private ArrayList<String> original;	
	/**
	 * <ul>
	 * <li><b><i>modified</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * An {@link ArrayList}<{@link String}> which contains the modified source code.
	 * </li>
	 * </ul>
	 */
	private ArrayList<String> modified;
	/**
	 * <ul>
	 * <li><b><i>lineMap</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * A {@link Map}<{@link Integer}, {@link Integer}> which contains the corresponding line's indexes from the original and the modified source code. 
	 * </li>
	 * </ul>
	 */
	private Map<Integer, Integer> lineMap;
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>SourceCodeWmpc</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link SourceCodeWmpc}({@link FileTypes} {@code type)}</p>
	 * <br>	
	 * Constructor which initializes the attributes and sets the file's type 
	 * 
	 * @param  type - this {@code FileTypes} type will be the source code
	 * </li>
	 * </ul>
	 */
	public SourceCodeWmpc(FileTypes type){
		this.type = type;
		original = new ArrayList<String>();
		modified = new ArrayList<String>();
		lineMap = new HashMap<Integer, Integer>();
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>setType</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public void setType(}{@link FileTypes} {@code type)}</p>
	 * <br>	
	 * Sets the type of source code. 
	 * 
	 * @param  type - this {@code FileTypes} type will be the source codes type
	 * </li>
	 * </ul>
	 */
	public void setType(FileTypes type) {
		this.type = type;
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>getType</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link FileTypes} {@code getType()}</p>
	 * <br>	
	 * Returns the type of source code.
	 * 
	 * @return the type of source code
	 * </li>
	 * </ul>
	 */
	public FileTypes getType() {
		return type;
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>setOriginal</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public void setOriginal(}{@link ArrayList}<{@link String}> {@code list)}</p>
	 * <br>	
	 * Sets the original source code with {@code list}.
	 * 
	 * @param  list - this will be the original source code
	 * </li>
	 * </ul>
	 */
	public void setOriginal(ArrayList<String> list) {
		original = list;
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>getOriginal</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link ArrayList}<{@link String}> {@code getOriginal()}</p>
	 * <br>	
	 * Returns the original list from the source code.
	 * 
	 * @return  the original source code
	 * </li>
	 * </ul>
	 */
	public ArrayList<String> getOriginal() {
		return original;		
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>addToOriginal</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public void addToOriginal(}{@link String} {@code str)}</p>
	 * <br>	
	 * Adds to the list of original source code {@code str}.
	 * 
	 * @param  str - this {@code String} will be added to the list
	 * </li>
	 * </ul>
	 */
	public void addToOriginal(String str) {
		original.add(str);
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>getFromOriginal</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link String} {@code getFromOriginal(int index)}</p>
	 * <br>	
	 * Returns the string from the list of original source code from {@code index}.
	 * 
	 * @param  index - from this index will be returned the string
	 * @return the {@code String} from the {@code index}
	 * </li>
	 * </ul>
	 */
	public String getFromOriginal(int index) {
		return original.get(index);
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>setModified</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public void setsetModifiedOriginal(}{@link ArrayList}<{@link String}> {@code list)} </p>
	 * <br>	
	 * Sets the modified source code with {@code list}.
	 * 
	 * @param  list - this will be the modified source code
	 * </li>
	 * </ul>
	 */
	public void setModified(ArrayList<String> list) {
		modified = list;
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>getModified</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link ArrayList}<{@link String}> {@code getModified()}</p>
	 * <br>	
	 * Returns the list of modified source code.
	 * 
	 * @return  the modified source code
	 * </li>
	 * </ul>
	 */
	public ArrayList<String> getModified() {
		return modified;		
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>addToModified</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public void addToModified(}{@link String} {@code str)}</p>
	 * <br>	
	 * Adds to the list of modified source code {@code str}.
	 * 
	 * @param  str - this {@code String} will be added to the list
	 * </li>
	 * </ul>
	 */
	public void addToModified(String str) {
		modified.add(str);
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>getFromModified</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link String} {@code getFromModified(int index)}</p>
	 * <br>	
	 * Returns the string from the list of modified source code from {@code index}.
	 * 
	 * @param  index - from this index will be returned the string
	 * @return the string from {@code index}
	 * </li>
	 * </ul>
	 */
	public String getFromModified(int index) {
		return modified.get(index);
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>setLineMap</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public void setLineMap(}{@link Map}<{@link Integer}, {@link Integer}> {@code map)}</p>
	 * <br>	
	 * Sets the line map with corresponding indexes with {@code map}.
	 * 
	 * @param  map - this will be the line map
	 * </li>
	 * </ul>
	 */
	public void setLineMap(Map<Integer, Integer> map) {
		this.lineMap = map;
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>getLineMap</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link Map}<{@link Integer}, {@link Integer}> {@code getLineMap()}</p>
	 * <br>	
	 * Returns the line map with corresponding indexes.
	 * 
	 * @return the line map
	 * </li>
	 * </ul>
	 */
	public Map<Integer, Integer> getLineMap() {
		return lineMap;
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>addKey</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public void addKey(int key, int value)}</p>
	 * <br>	
	 * Adds to the line map a new (key, value) pair.
	 * 
	 * @param key - this will be the new key, value pair's key 
	 * @param value - this will be the new key, value pair's value
	 * </li>
	 * </ul>
	 */
	public void addKey(int key, int value) {
		lineMap.put(key, value);
	}
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>getValue</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public int getValue(int key)}</p>
	 * <br>	
	 * Returns an element from the line map with key which corresponds with {@code key}.
	 * 
	 * @param key - from this key value will be returned the line map element 
	 * @return the line map element from {@code key} value
	 * </li>
	 * </ul>
	 */
	public int getValue(int key) {
		return lineMap.get(key);
	}
	/**
	 * <ul style="margin-top: 24px;">
	 * <li><b><i>getContentIndexes</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link ArrayList}<{@link Object}> {@code getContentIndexes()}</p>
	 * <br>	
	 * Supplies a list containing the indexes at which new file contents begin within the source code, and also the names of these files.    
	 * 
	 * @return	an {@code ArrayList<Object>} containing ({@code index}, {@code fileName}) pairs 
	 * </li>
	 * </ul>
	 */
	public ArrayList<Object> getContentIndexes(){
		ArrayList<Object> result = new ArrayList<Object>();
		String str;
		int k = 0;
		
		str = original.get(0);
		if (str.matches("^#{5} .* #{5}$")) {
			result.add(str.replaceAll("(^#{5} )(.*)( #{5})", "$2"));
		}
		
		for (int i = 1; i < original.size(); i++){
			str = original.get(i);
			
			if (str.matches("^#{5} .* #{5}$")) {
				k++;
				result.add(i-1+k);
				result.add(str.replaceAll("(^#{5} )(.*)( #{5})", "$2"));
			}
		}
		
		result.add(original.size());

		return result;
	}

}
